package com.cocostudio.erpapp.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import android.content.Context;
import android.os.Environment;
import android.os.StatFs;

public class StorageManager {
    private static final String CACHE_DIR = "cmef2013";
    public static final int TYPE_INTERNAL_STORAGE = 0;
    public static final int TYPE_EXTERNAL_STORAGE = 1;
    public static final int TYPE_NO_AVAILABLE = -1;

    public static int getBestStorage(Context context, long fileSize) {
        int type = -1;
        if (isExternalStorageMounted()) {
            if (getExternalAvailableSpace() <= fileSize) {
                shrinkExternalSpace(context, fileSize);
            }
            if (getExternalAvailableSpace() > fileSize) {
                type = TYPE_EXTERNAL_STORAGE;
                File dir = getExternalDirectory();
                if (!dir.exists()) {
                    dir.mkdirs();
                }
            }
        } else {
            if (getFileDirAvailableSpace(context) <= fileSize) {
                shrinkInternalSpace(context, fileSize);
            }
            type = TYPE_INTERNAL_STORAGE;
        }
        return type;
    }

    public static OutputStream getOutputStream(Context context, int storageType, String fileName) throws FileNotFoundException {
        if (TYPE_EXTERNAL_STORAGE == storageType) {
            return new FileOutputStream(new File(getExternalDirectory(), fileName));
        } else {
            return context.openFileOutput(fileName, 0);
        }
    }

    public static File getFile(Context context, String fileName) {
        File file = getFile(context, TYPE_EXTERNAL_STORAGE, fileName);
        if (file == null) {
            file = getFile(context, TYPE_INTERNAL_STORAGE, fileName);
        }
        return file;
    }

    public static File getFile(Context context, int storageType, String fileName) {
        if (TYPE_EXTERNAL_STORAGE == storageType) {
            return new File(getExternalDirectory(), fileName);
        } else {
            return new File(getInternalDirectory(context), fileName);
        }
    }

    public static boolean isExternalStorageMounted() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

    private static long getExternalAvailableSpace() {
        StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
        long space = (long) statFs.getAvailableBlocks() * (long) statFs.getBlockSize();
        return space;
    }

    private static long getFileDirAvailableSpace(Context context) {
        StatFs statFs = new StatFs(context.getFilesDir().getAbsolutePath());
        long space = (long) statFs.getAvailableBlocks() * (long) statFs.getBlockSize();
        return space;
    }

    private static File getExternalDirectory() {
        return new File(Environment.getExternalStorageDirectory(), CACHE_DIR);
    }

    private static File getInternalDirectory(Context context) {
        return context.getFilesDir();
    }

    private static void shrinkExternalSpace(Context context, long fileSize) {
        shrinkSpace(fileSize, getExternalDirectory());
    }

    private static void shrinkInternalSpace(Context context, long fileSize) {
        shrinkSpace(fileSize, getInternalDirectory(context));
    }

    private static void shrinkSpace(long fileSize, File dir) {
        long deleteSize = 0;
        while (deleteSize <= fileSize) {
            File[] files = dir.listFiles();
            if (files == null || files.length == 0) {
                break;
            }
            for (int i = 0; i < files.length; i++) {
                if (files[i].isFile()) {
                    files[i].delete();
                }
            }
        }
    }

    public static void removeFiles(File file) {
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (File f : files) {
                    removeFiles(f);
                }
                file.delete();
            } else {
                file.delete();
            }
        }
    }

    public static void clearAllCache(Context context) {
        removeFiles(getExternalDirectory());
        removeFiles(getInternalDirectory(context));
    }
}
